{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 基于梯度下降法编写程序实现回归算法，并自行使用模拟数据进行测试，同时对同样的模拟数据进行两种算法的比较(python sklearn LinearRegression和自己实现的线性回归算法)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#建造一个最简单的阶梯下降\n",
    "def regression(data,alpha,lamba):\n",
    "    import numpy as np\n",
    "    n=len(data[0])-1\n",
    "    theta=np.zeros(n)\n",
    "    for times in range(100):\n",
    "        for d in data:\n",
    "            x=d[:-1]\n",
    "            y=d[-1]\n",
    "            g=np.dot(theta,x)-y\n",
    "            theta=theta-alpha*g*x+lamda*theta\n",
    "        print(times,theta)\n",
    "    return theta"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "构造一个完整的梯度下降算法\n",
    "==="
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 329,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 数据校验\n",
    "def err(X, Y):\n",
    "    X=X.values.T\n",
    "    if len(X[0]) != len(Y):\n",
    "        raise Exception(\"参数异常\")\n",
    "    else:\n",
    "        m = len(X[0])\n",
    "        for l in X:\n",
    "            if len(l) != m:\n",
    "                raise Exception(\"参数异常\")\n",
    " \n",
    "\n",
    "    # 计算差异值\n",
    "def diffy(x, y, a):\n",
    "    import numpy as np\n",
    "    import pandas as pd\n",
    "    x=x.values.T\n",
    "    y=y.values\n",
    "    lx = len(x)\n",
    "    la = len(a)\n",
    "    if lx == la:\n",
    "        result=np.dot(a,x)\n",
    "        return np.array(y - result)\n",
    "    elif lx + 1 == la:\n",
    "        la=la-1\n",
    "        result=np.dot(x,a[0:la])+np.array(a[-1])\n",
    "        return np.array(y - result)\n",
    "    else :\n",
    "        raise Exception(\"参数异常\")\n",
    "\n",
    "                \n",
    "## 要求X必须是List集合，Y也必须是List集合\n",
    "def fit(s, Y, alphas, threshold=1e-6, maxIter=200, intercept=True):\n",
    "    import math\n",
    "    import numpy as np\n",
    "    if intercept:\n",
    "        X=s.iloc[:,:]\n",
    "        X['cs']=1\n",
    "    else:\n",
    "        X=s\n",
    "    ## 校验\n",
    "    err(X, Y)\n",
    "    ## 开始模型构建\n",
    "    l = len(alphas)\n",
    "    m = len(Y)\n",
    "    n = len(X.T)\n",
    "    B = [True for i in range(l)]\n",
    "    ## 差异性(损失值)\n",
    "    J = [np.nan for i in range(l)]\n",
    "   \n",
    "    # 1. 随机初始化0值(全部为0), a的最后一列为常数项\n",
    "    a = np.zeros([l,n])\n",
    "    # 2. 开始计算\n",
    "    for times in range(maxIter):\n",
    "        for i in range(l):\n",
    "            if not B[i]:\n",
    "                # 如果当前alpha的值已经计算到最优解了，那么不进行继续计算\n",
    "                continue\n",
    "            \n",
    "          \n",
    "            ta=a[i]\n",
    "            alpha = alphas[i]\n",
    "            ta+=a[i]+alpha*diffy(X,Y,a[i]).dot(X)\n",
    "            \n",
    "               \n",
    "            ## 计算完一个alpha值的0的损失函数\n",
    "            flag = True\n",
    "            js = 0\n",
    "            js += np.power(diffy(X, Y, a[i]),2).sum()\n",
    "            if js > J[i]:\n",
    "                flag = False\n",
    "                break;\n",
    "            if flag:\n",
    "                J[i] = js\n",
    "                a[i]=ta\n",
    "            else:\n",
    "                # 标记当前alpha的值不需要再计算了\n",
    "                B[i] = False        \n",
    "        ## 计算完一个迭代，当目标函数/损失函数值有一个小于threshold的结束循环\n",
    "        r = [0 for j in J if j <= threshold]\n",
    "        if len(r) > 0:\n",
    "            break\n",
    "        # 如果全部alphas的值都结算到最后解了，那么不进行继续计算\n",
    "        r = [0 for b in B if not b]\n",
    "        if len(r) > 0:\n",
    "            break;\n",
    "    # 3. 获取最优的alphas的值以及对应的0值\n",
    "    min_a = a[0]\n",
    "    min_j = J[0]\n",
    "    min_alpha = alphas[0]\n",
    "    for i in range(l):\n",
    "        if J[i] < min_j:\n",
    "            min_j = J[i]\n",
    "            min_a = a[i]\n",
    "            min_alpha = alphas[i]\n",
    "    \n",
    "    print(\"最优的alpha值为:\",min_alpha)\n",
    "    \n",
    "    # 4. 返回最终的0值\n",
    "    return min_a\n",
    "\n",
    "# 预测结果\n",
    "def hcpredict(X,a):\n",
    "    if len(X.T)==len(a):\n",
    "        Y=X.dot(a)\n",
    "    else:\n",
    "        la=len(a)-1\n",
    "        Y=X.dot(a[0:la])+np.array([a[-1]])\n",
    "    return Y\n",
    "\n",
    "# 计算实际值和预测值之间的相关性\n",
    "def hcScore(y,py):\n",
    "    if len(y) != len(py):\n",
    "        raise Exception(\"参数异常\")\n",
    "    import math \n",
    "    import numpy as np\n",
    "    avgy = np.average(y)\n",
    "    m = len(y)\n",
    "    rss = 0.0\n",
    "    tss = 0\n",
    "    for i in range(m):\n",
    "        rss += math.pow(y[i] - py[i], 2)\n",
    "        tss += math.pow(y[i] - avgy, 2)\n",
    "    r = 1.0 - 1.0 * rss / tss\n",
    "    return r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 330,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0     2\n",
       "1     4\n",
       "2     6\n",
       "3     8\n",
       "4    10\n",
       "5    12\n",
       "6    14\n",
       "7    16\n",
       "Name: chinese, dtype: int64"
      ]
     },
     "execution_count": 330,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "df=pd.DataFrame({\n",
    "    'math':[1,2,3,4,5,6,7,8],\n",
    "    'en':[1,2,3,4,5,6,7,8],\n",
    "    'chinese':[2,4,6,8,10,12,14,16]\n",
    "})\n",
    "\n",
    "x1=df[['en','math']]\n",
    "y2=df['chinese']\n",
    "\n",
    "\n",
    "d1=df\n",
    "\n",
    "# a = np.ones([1,len(x.T)])\n",
    "# ts=a+diffy(x,y,a).dot(x)\n",
    "# # diffy(x,y,a)\n",
    "# ts\n",
    "d1\n",
    "# diffy(x,y,a)\n",
    "# x.dot(alp)\n",
    "y2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 332,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "最优的alpha值为: 0.00572236765935\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>chinese</th>\n",
       "      <th>en</th>\n",
       "      <th>math</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>4</td>\n",
       "      <td>2</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>6</td>\n",
       "      <td>3</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>8</td>\n",
       "      <td>4</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>10</td>\n",
       "      <td>5</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>12</td>\n",
       "      <td>6</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>14</td>\n",
       "      <td>7</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>16</td>\n",
       "      <td>8</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   chinese  en  math\n",
       "0        2   1     1\n",
       "1        4   2     2\n",
       "2        6   3     3\n",
       "3        8   4     4\n",
       "4       10   5     5\n",
       "5       12   6     6\n",
       "6       14   7     7\n",
       "7       16   8     8"
      ]
     },
     "execution_count": 332,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alp=fit(x,y,alphas=np.logspace(-3,2,100))\n",
    "yp=hcpredict(x,alp)\n",
    "hcScore(y,yp)\n",
    "df\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 249,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "import warnings\n",
    "import sklearn\n",
    "from sklearn.linear_model import LinearRegression,Ridge, LassoCV, RidgeCV, ElasticNetCV\n",
    "from sklearn.preprocessing import PolynomialFeatures\n",
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.linear_model.coordinate_descent import ConvergenceWarning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 250,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "## 设置字符集，防止中文乱码\n",
    "mpl.rcParams['font.sans-serif']=[u'simHei']\n",
    "mpl.rcParams['axes.unicode_minus']=False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 344,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# warnings.filterwarnings(action = 'ignore', category=ConvergenceWarning)\n",
    "## 创建模拟数据\n",
    "np.random.seed(0)\n",
    "np.set_printoptions(linewidth=1000, suppress=True)\n",
    "N = 10\n",
    "x = np.linspace(0, 6, N) + np.random.randn(N)\n",
    "y = 1.8*x**3 + x**2 - 14*x - 7 + np.random.randn(N)\n",
    "x.shape = -1, 1\n",
    "y.shape = -1, 1\n",
    "x=pd.DataFrame(x)\n",
    "x.columns=['moni']\n",
    "y=pd.DataFrame(y)\n",
    "y=y.iloc[:,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 345,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>moni</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.764052</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1.066824</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2.312071</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4.240893</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4.534225</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>2.356055</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>4.950088</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>4.515309</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>5.230114</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>6.410599</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       moni\n",
       "0  1.764052\n",
       "1  1.066824\n",
       "2  2.312071\n",
       "3  4.240893\n",
       "4  4.534225\n",
       "5  2.356055\n",
       "6  4.950088\n",
       "7  4.515309\n",
       "8  5.230114\n",
       "9  6.410599"
      ]
     },
     "execution_count": 345,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# ma = fit(x,y,np.logspace(-4,-2,100), intercept=True)\n",
    "# y_hat2 = hcpredict(x_hat, ma)\n",
    "# s2 = hcScore(y, predict(x,ma))\n",
    "\n",
    "# if len(x_hat.T)==len(ma):\n",
    "#     Y=x_hat.dot(ma)\n",
    "# else:\n",
    "#     la=len(ma)-1\n",
    "#     Y=x_hat.dot(ma[0:(len(ma)-1)])+np.array([ma[-1]])\n",
    " \n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 346,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\hc\\Anaconda3\\lib\\site-packages\\matplotlib\\pyplot.py:524: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).\n",
      "  max_open_warning, RuntimeWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.837437698825\n",
      "模块自带实现===============\n",
      "参数列表: [ 72.0576022]\n",
      "截距: -163.711329657\n",
      "最优的alpha值为: 0.00215443469003\n",
      "自定义实现模型=============\n",
      "参数列表: [ 33.46912664   5.75239347]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214141a9a58>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21414517710>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2141452e208>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21412a32550>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21414549b70>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214144e7c18>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214144f4b00>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21415582a90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214155a7320>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2141556d630>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214144f0390>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21415567908>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214145175c0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214155c20f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214141a9a90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21415567d68>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21415563c18>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21415567710>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21412a6a240>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2141556d4a8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214155826a0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2141569d898>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x214156c8f98>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2141569d208>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21415619a58>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(12,6), facecolor='w')\n",
    "\n",
    "## 模拟数据产生\n",
    "x_hat = np.linspace(x.values.min(), x.values.max(), num=100)\n",
    "x_hat.shape = -1,1\n",
    "x_hat=pd.DataFrame(x_hat,columns=['moni'])\n",
    "## 线性模型\n",
    "model = LinearRegression()\n",
    "model.fit(x,y)\n",
    "y_hat = model.predict(x_hat)\n",
    "s1 = calcRScore(y, model.predict(x))\n",
    "print(model.score(x,y)) ## 自带R^2输出\n",
    "print (\"模块自带实现===============\")\n",
    "print (\"参数列表:\", model.coef_)\n",
    "print (\"截距:\", model.intercept_)\n",
    "\n",
    "\n",
    "## 自模型\n",
    "ma = fit(x,y,np.logspace(-4,-2,100), intercept=True)\n",
    "y_hat2 = hcpredict(x_hat, ma)\n",
    "s2 = hcScore(y, predict(x,ma))\n",
    "print (\"自定义实现模型=============\")\n",
    "print (\"参数列表:\", ma)\n",
    "\n",
    "## 开始画图\n",
    "plt.plot(x, y, 'ro', ms=10, zorder=3)\n",
    "plt.plot(x_hat, y_hat, color='#b624db', lw=2, alpha=0.75, label=u'Python模型，$R^2$:%.3f' % s1, zorder=2)\n",
    "plt.plot(x_hat, y_hat2, color='#6d49b6', lw=2, alpha=0.75, label=u'自己实现模型，$R^2$:%.3f' % s2, zorder=1)\n",
    "plt.legend(loc = 'upper left')\n",
    "plt.grid(True)\n",
    "plt.xlabel('X', fontsize=16)\n",
    "plt.ylabel('Y', fontsize=16)\n",
    "\n",
    "plt.suptitle(u'自定义的线性模型和模块中的线性模型比较', fontsize=22)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 200,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.066824</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1.120801</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1.174779</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1.228756</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1.282734</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          0\n",
       "0  1.066824\n",
       "1  1.120801\n",
       "2  1.174779\n",
       "3  1.228756\n",
       "4  1.282734"
      ]
     },
     "execution_count": 200,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (<ipython-input-19-f352236cae76>, line 5)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-19-f352236cae76>\"\u001b[1;36m, line \u001b[1;32m5\u001b[0m\n\u001b[1;33m    print \"自带梯度下降法R方:\", clf.score(x,y1)\u001b[0m\n\u001b[1;37m                     ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "from sklearn.ensemble import GradientBoostingRegressor\n",
    "clf = GradientBoostingRegressor()\n",
    "y1 = y.ravel()\n",
    "clf.fit(x,y1)\n",
    "print \"自带梯度下降法R方:\", clf.score(x,y1)\n",
    "y_hat3=clf.predict(x_hat)\n",
    "s3=calcRScore(y, clf.predict(x))\n",
    "\n",
    "## 开始画图\n",
    "plt.plot(x, y, 'ro', ms=10, zorder=3)\n",
    "plt.plot(x_hat, y_hat, color='#b624db', lw=2, alpha=0.75, label=u'Python模型，$R^2$:%.3f' % s1, zorder=2)\n",
    "plt.plot(x_hat, y_hat2, color='#6d49b6', lw=2, alpha=0.75, label=u'自己实现模型，$R^2$:%.3f' % s2, zorder=1)\n",
    "plt.plot(x_hat, y_hat3, color='#6daaba', lw=2, alpha=0.75, label=u'自带梯度下降方法，$R^2$:%.3f' % s3, zorder=1)\n",
    "plt.legend(loc = 'upper left')\n",
    "plt.grid(True)\n",
    "plt.xlabel('X', fontsize=16)\n",
    "plt.ylabel('Y', fontsize=16)\n",
    "\n",
    "plt.suptitle(u'自定义的线性模型和模块中的线性模型比较', fontsize=22)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9999999989274823"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
